package lumis.service.portalmanagement.webfilereplication;

import java.util.ArrayList;
import java.util.Collection;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.persistence.EntityManager;

import lumis.doui.control.password.PasswordControl;
import lumis.doui.processaction.ProcessActionHandler;
import lumis.doui.source.Source;
import lumis.portal.PortalException;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.webfilereplication.WebFileReplication;
import lumis.portal.webfilereplication.WebFileReplicationProperty;
import lumis.portal.webfilereplication.WebFileReplicationPropertyValue;
import lumis.portal.webfilereplication.WebFileReplicationType;
import lumis.util.XmlUtil;


/**
 * Process Action Handler for all Web File Replication actions.
 * 
 * 
 * @version $Revision: 13092 $ $Date: 2011-05-28 18:19:06 -0300 (Sat, 28 May 2011) $
 * @since 6.0.0
 */
@SuppressWarnings("unchecked")
public class WebFileReplicationProcessActionHandler extends ProcessActionHandler<Source>
{

	public void processAction() throws PortalException
	{
		String actionType = XmlUtil.readAttributeString("actionType", processActionNode);

		if (actionType.equals("add"))
			addWebFileReplication();
		if (actionType.equals("update"))
			updateWebFileReplication();
		if (actionType.equals("delete"))
			deleteWebFileReplication();

		addDefaultResponse();
	}

	/**
	 * Adds a replication.
	 * 
	 * @throws PortalException
	 *             In any error occurs adding the replication.
	 * @since 6.0.0
	 */
	protected void addWebFileReplication() throws PortalException
	{
		EntityManager entityManager = ManagerFactory.getEntityManager();

		String name = getParameter("name", String.class);
		String type = getParameter("type", String.class);
		String filterChannelId = getParameter("filterChannelId", String.class);
		String filterPath = getParameter("filterPath", String.class);

		try
		{
			// Validates the regular expression.
			validateRegExp(filterPath);
		}
		catch (PatternSyntaxException e) 
		{
			throw new PortalException("STR_REGEXP_INVALID",getResource(),e);
		}
		
		WebFileReplication webFileReplication = new WebFileReplication();
		WebFileReplicationType webFileReplicationType = entityManager.getReference(WebFileReplicationType.class, type);

		webFileReplication.setName(name);
		webFileReplication.setType(webFileReplicationType);
		webFileReplication.setFilterChannelId(filterChannelId);
		webFileReplication.setFilterPath(filterPath);

		setPropertyValuesFromRequest(webFileReplication);

		entityManager.persist(webFileReplication);
	}

	/**
	 * Updates a replication.
	 * 
	 * @throws PortalException
	 *             In any error occurs updating the replication.
	 * @since 6.0.0
	 */
	protected void updateWebFileReplication() throws PortalException
	{
		EntityManager entityManager = ManagerFactory.getEntityManager();

		String id = getParameter("id", String.class);
		String name = getParameter("name", String.class);
		String type = getParameter("type", String.class);
		String filterChannelId = getParameter("filterChannelId", String.class);
		String filterPath = getParameter("filterPath", String.class);

		try
		{
			// Validates the regular expression.
			validateRegExp(filterPath);
		}
		catch (PatternSyntaxException e) 
		{
			throw new PortalException("STR_REGEXP_INVALID",getResource(),e);
		}
		
		WebFileReplicationType webFileReplicationType = entityManager.getReference(WebFileReplicationType.class, type);

		WebFileReplication webFileReplication = entityManager.find(WebFileReplication.class, id);
		webFileReplication.setName(name);
		webFileReplication.setType(webFileReplicationType);
		webFileReplication.setFilterChannelId(filterChannelId);
		webFileReplication.setFilterPath(filterPath);

		setPropertyValuesFromRequest(webFileReplication);

		entityManager.persist(webFileReplication);
	}

	/**
	 * Removes a replication.
	 * 
	 * @since 6.0.0
	 */
	protected void deleteWebFileReplication()
	{
		EntityManager entityManager = ManagerFactory.getEntityManager();

		String[] ids = (String[]) getParameter("id");
		for (String id : ids)
		{
			WebFileReplication webFileReplication = entityManager.getReference(WebFileReplication.class, id);
			entityManager.remove(webFileReplication);
		}
	}

	/**
	 * Sets the custom properties values from the request into the replication.
	 * 
	 * @param replication
	 *            The replication to be filled.
	 * @since 6.0.0
	 */
	private void setPropertyValuesFromRequest(WebFileReplication replication)
	{
		WebFileReplicationType type = replication.getType();
		Collection<WebFileReplicationProperty> properties = type.getProperties();
		Collection<WebFileReplicationPropertyValue> propertyValues = new ArrayList<WebFileReplicationPropertyValue>();

		for (WebFileReplicationProperty property : properties)
		{
			// TODO: the control should handle the request parameter doing the appropriate conversions
			String value = douiContext.getRequest().getParameter(property.getId());
			
			// create the value entity
			WebFileReplicationPropertyValue propertyValue = new WebFileReplicationPropertyValue();
			propertyValue.setProperty(property);
			propertyValue.setReplication(replication);
			propertyValue.setValue(value);
			
			// if the property data type is PasswordDataType handles the PASSWORD_NOT_SPECIFIED situation 
			if ((property.getDataType().equals(PasswordDataType.class.getName())) 
					&& (PasswordControl.PASSWORD_NOT_SPECIFIED.equals(value)))
			{
				WebFileReplicationPropertyValue oldValue = findOldPropertyValue(replication, property);
				handlePasswordField(propertyValue, oldValue);
			}

			propertyValues.add(propertyValue);
		}

		replication.setPropertyValues(propertyValues);
	}
	
	/**
	 * Handles the password field when the new value is PasswordControl.PASSWORD_NOT_SPECIFIED.
	 * @param newValue	the new value for the password property.
	 * @param oldValue	the old value for the password property.
	 */
	private void handlePasswordField(WebFileReplicationPropertyValue newValue, WebFileReplicationPropertyValue oldValue)
	{
		if (PasswordControl.PASSWORD_NOT_SPECIFIED.equals(newValue.getValue()))
		{
			// in this case, the password was filled before but now it was not changed
			if ((oldValue.getValue() != null) 
					&& (!oldValue.getValue().equals("")))
			{
				newValue.setValue(oldValue.getValue());
			}
			else
			{
				newValue.setValue(null);
			}
		}
	}
	
	/**
	 * Finds the old value for a given replication property.
	 * @param replication	the replication
	 * @param property		the property.
	 * @return				the old replication property value.
	 */
	private WebFileReplicationPropertyValue findOldPropertyValue(WebFileReplication replication, WebFileReplicationProperty property)
	{
		WebFileReplicationPropertyValue propertyOldValue = null;
		for (WebFileReplicationPropertyValue propertyValue: replication.getPropertyValues())
		{
			if (propertyValue.getProperty().getId().equals(property.getId()))
			{
				propertyOldValue = propertyValue;
				break;
			}
		}
		return propertyOldValue;
	}
	
	/**
	 * Validates a regular expression.
	 * @param regExp the regular expression for validate.
	 * @throws PatternSyntaxException if the regular expression is invalid.
	 */
	private void validateRegExp(String regExp) throws PatternSyntaxException
	{
		if ((regExp != null) && (!regExp.equalsIgnoreCase("")))
		{
			Pattern.compile(regExp);
		}
	}
}